package cn.xs.core.dao.impl;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import cn.xs.core.dao.BaseDao;

/**
 * BaseDao接口的抽象实现类,子类必须自己实现save方法
 * @author xs
 *
 * @param <T>
 */
public abstract class BaseDaoImpl<T> implements BaseDao<T> {

	Class clazz;
	private QueryRunner queryRunner;
	private String findSql;
	private String findAllSql;
	private String deleteSql;
	private Method[] methods;
	
	public BaseDaoImpl(){
		ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
		clazz = (Class) type.getActualTypeArguments()[0];
		initSql();
		methods = clazz.getMethods();
	}
	
	/**
	 * 初始化sql语句
	 */
	private void initSql() {
		StringBuffer sb = new StringBuffer();
		//findAllSql = select * from t_???;
		sb.append("select * from t_");
		sb.append(clazz.getSimpleName());
		findAllSql = sb.toString();
		//findSql = select * from t_??? where id = ?;
		sb.append(" where id = ?;");
		findSql = sb.toString();
		//deleteSql = delete from t_??? where id = ?;
		sb = new StringBuffer();
		sb.append("delete from t_");
		sb.append(clazz.getSimpleName());
		sb.append(" where id =?;");
		deleteSql =  sb.toString();
	}

	public void delete(String id) {
		try {
			queryRunner.update(deleteSql,id);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings("unchecked")
	public T find(String id) {
		try {
			return (T) queryRunner.query(findSql, new BeanHandler(clazz), new Object[]{id});
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		try {
			return (List<T>) queryRunner.query(findAllSql, new BeanListHandler(clazz));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	
	/**
	 * 保存方法,子类自己实现
	 */
	public abstract void save(T entity);

	/**
	 * 更新方法,先删除后增
	 */
	public void update(T entity) {
		String id = getValue(entity, "id");
		delete(id);
		save(entity);
	}

	/**
	 * 通过反射拿到该字段的值
	 * @param fieldName	字段名
	 * @return 实例对象的字段值
	 */
	private String getValue(T entity,String fieldName){
		String value = "";
		for(int i = 0;i<methods.length;i++){
			if(("get"+fieldName).toLowerCase().equals(methods[i].getName().toLowerCase())){
				try {
					value = (String) methods[i].invoke(entity);
				} catch (Exception e) {
					e.printStackTrace();
				} 
			}
		}
		return value;
	}
	
	public QueryRunner getQueryRunner() {
		return queryRunner;
	}
	public void setQueryRunner(QueryRunner queryRunner) {
		this.queryRunner = queryRunner;
	}
	public String getFindSql() {
		return findSql;
	}
	public void setFindSql(String findSql) {
		this.findSql = findSql;
	}
	public String getFindAllSql() {
		return findAllSql;
	}
	public void setFindAllSql(String findAllSql) {
		this.findAllSql = findAllSql;
	}
	public String getDeleteSql() {
		return deleteSql;
	}
	public void setDeleteSql(String deleteSql) {
		this.deleteSql = deleteSql;
	}
	
}
